/////////////////////////////////////////////////////////////////////////////
// This file is part of the "Java-DAP" project, a Java implementation
// of the OPeNDAP Data Access Protocol.
//
// Copyright (c) 2007 OPeNDAP, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
/////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections;
using System.IO;
using NDODS.DAP.Exceptions;
using NDODS.DAP.Utils;
using NDODS.DAP.XMLParser;

namespace NDODS.DAP.BaseTypes
{
    /// <summary> This class holds a <code>DArray</code> and a set of "Map"
    /// vectors.  The Map vectors are one-dimensional arrays corresponding
    /// to each dimension of the central <code>Array</code>.  Using this scheme, a
    /// <code>Grid</code> can represent, in a rectilinear array, data which is not
    /// in reality rectilinear.  An example will help make this clear.
    /// <p/>
    /// Assume that the following array contains measurements of some real
    /// quantity, conducted at nine different points in space:
    /// <p/>
    /// <code><pre>
    /// A = [ 1  2  3  4 ]
    /// [ 2  4  6  8 ]
    /// [ 3  6  9  12]
    /// </pre></code>
    /// <p/>
    /// To locate this <code>Array</code> in the real world, we could note the
    /// location of one corner of the grid, and the grid spacing.  This would allow
    /// us to calculate the location of any of the other points of the
    /// <code>Array</code>.
    /// <p/>
    /// This approach will not work, however, unless the grid spacing is
    /// precisely regular.  If the distance between Row 1 and Row 2 is not
    /// the same as the distance between Row 2 and Row 3, the scheme will
    /// break down.  The solution is to equip the <code>Array</code> with two
    /// <code>Map</code> vectors that define the location of each row or column of
    /// the array:
    /// <p/>
    /// <code><pre>
    /// A = [ 1  2  3  4 ] Row = [ 0 ]
    /// [ 2  4  6  8 ]       [ 3 ]
    /// [ 3  6  9  12]       [ 8 ]
    /// <p/>
    /// Column = [ 0  2  8  27]
    /// </pre></code>
    /// <p/>
    /// The real location of the point in the first row and column of the
    /// array is now exactly fixed at (0,0), and the point in the last row
    /// and last column is at (8,27).
    /// 
    /// </summary>
    /// <author>  jehamby
    /// </author>
    /// <version>  $Revision: 15901 $
    /// </version>
    /// <seealso cref="BaseType">
    /// </seealso>
    /// <seealso cref="DArray">
    /// </seealso>
    [Serializable]
    public class DGrid : DConstructor, IClientIO, ICloneable
    {
        /// <summary> Returns the OPeNDAP type name of the class instance as a <code>String</code>.
        /// 
        /// </summary>
        /// <returns> the OPeNDAP type name of the class instance as a <code>String</code>.
        /// </returns>
        public override String TypeName
        {
            get { return "Grid"; }
        }

        /// <summary> Return an Enumeration that can be used to iterate over the members of
        /// a Structure. This implementation provides access to the elements of
        /// the Structure. Each Object returned by the Enumeration can be cast to
        /// a BaseType.
        /// 
        /// </summary>
        /// <returns> An Enumeration
        /// </returns>
        public override IEnumerator Variables
        {
            get { return new EnumerateDGrid(this); }
        }

        /// <summary> The <code>Array</code> part of the <code>DGrid</code></summary>
        public const int ARRAY = 1;

        /// <summary> The Map part of the <code>DGrid</code></summary>
        public const int MAPS = 2;

        /// <summary> The Array component of this <code>DGrid</code>.</summary>
        protected internal DArray arrayVar;

        /// <summary> The Map component of this <code>DGrid</code>.</summary>
        protected internal ArrayList mapVars;

        /// <summary> Constructs a new <code>DGrid</code>.</summary>
        public DGrid() : this(null)
        {
        }

        /// <summary> Constructs a new <code>DGrid</code> with name <code>n</code>.
        /// 
        /// </summary>
        /// <param name="n">the name of the variable.
        /// </param>
        public DGrid(String n) : base(n)
        {
            mapVars = ArrayList.Synchronized(new ArrayList(10));
        }

        /// <summary> Returns a clone of this <code>DGrid</code>.  A deep copy is performed
        /// on all data inside the variable.
        /// 
        /// </summary>
        /// <returns> a clone of this <code>DGrid</code>.
        /// </returns>
        public override Object Clone()
        {
            DGrid g = (DGrid) base.Clone();
            g.arrayVar = (DArray) arrayVar.Clone();
            g.mapVars = ArrayList.Synchronized(new ArrayList(10));
            for (int i = 0; i < mapVars.Count; i++)
            {
                BaseType bt = (BaseType) mapVars[i];
                g.mapVars.Add(bt.Clone());
            }
            return g;
        }

        /// <summary> Returns the number of variables contained in this object. For simple and
        /// vector type variables, it always returns 1. To count the number
        /// of simple-type variable in the variable tree rooted at this variable, set
        /// <code>leaves</code> to <code>true</code>.
        /// 
        /// </summary>
        /// <param name="leaves">If true, count all the simple types in the `tree' of
        /// variables rooted at this variable.
        /// </param>
        /// <returns> the number of contained variables.
        /// </returns>
        public override int ElementCount(bool leaves)
        {
            if (!leaves)
                return mapVars.Count + 1;
                // Number of Maps plus 1 Array component
            else
            {
                int count = 0;
                //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                for (IEnumerator e = mapVars.GetEnumerator(); e.MoveNext();)
                {
                    //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                    BaseType bt = (BaseType) e.Current;
                    count += bt.ElementCount(leaves);
                }
                count += arrayVar.ElementCount(leaves);
                return count;
            }
        }

        /// <summary> Adds a variable to the container.
        /// 
        /// </summary>
        /// <param name="v">   the variable to add.
        /// </param>
        /// <param name="part">the part of the <code>DGrid</code> to be modified.  Allowed
        /// values are <code>ARRAY</code> or <code>MAPS</code>.
        /// </param>
        /// <throws>  IllegalArgumentException if an invalid part was given. </throws>
        public override void addVariable(BaseType v, int part)
        {
            if (!(v is DArray))
                throw new ArgumentException("Grid `" + Name + "'s' member `" + arrayVar.Name + "' must be an array");

            v.Parent = this;

            switch (part)
            {
                case ARRAY:
                    arrayVar = (DArray) v;
                    return;


                case MAPS:
                    mapVars.Add(v);
                    return;


                default:
                    throw new ArgumentException("addVariable(): Unknown Grid part");
            }
        }

        /// <summary> Returns the named variable.
        /// 
        /// </summary>
        /// <param name="name">the name of the variable.
        /// </param>
        /// <returns> the named variable.
        /// </returns>
        /// <throws>  NoSuchVariableException if the named variable does not </throws>
        /// <summary>                                 exist in this container.
        /// </summary>
        public override BaseType getVariable(String name)
        {
            int dotIndex = name.IndexOf('.');

            if (dotIndex != - 1)
            {
                // name contains "."

                String aggregate = name.Substring(0, (dotIndex) - (0));
                String field = name.Substring(dotIndex + 1);

                BaseType aggRef = getVariable(aggregate);
                if (aggRef is DConstructor)
                    return ((DConstructor) aggRef).getVariable(field);
                    // recurse
                else
                {
                } // fall through to throw statement
            }
            else
            {
                if (arrayVar.Name.Equals(name))
                    return arrayVar;

                //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                for (IEnumerator e = mapVars.GetEnumerator(); e.MoveNext();)
                {
                    //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                    BaseType v = (BaseType) e.Current;
                    if (v.Name.Equals(name))
                        return v;
                }
            }
            throw new NoSuchVariableException("DGrid.getVariable() No such variable: '" + name + "'");
        }

        /// <summary> Gets the indexed variable. For a DGrid the index 0 returns the <code>DArray</code> and
        /// indexes 1 and higher return the associated map <code>Vector</code>s.
        /// 
        /// </summary>
        /// <param name="index">the index of the variable in the <code>Vector</code> Vars.
        /// </param>
        /// <returns> the indexed variable.
        /// </returns>
        /// <throws>  NoSuchVariableException if the named variable does not </throws>
        /// <summary>                                 exist in this container.
        /// </summary>
        public override BaseType getVar(int index)
        {
            if (index == 0)
            {
                return (arrayVar);
            }
            else
            {
                int i = index - 1;
                if (i < mapVars.Count)
                    return ((BaseType) mapVars[i]);
                else
                    throw new NoSuchVariableException("DGrid.getVariable() No Such variable: " + index + " - 1)");
            }
        }


        //UPGRADE_NOTE: Field 'EnclosingInstance' was added to class 'EnumerateDGrid' to access its enclosing instance. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1019'"
        /// <summary> Private class for implemantation of the Enumeration. Because
        /// DStructure and DSequence are simpler classes and use a single Vector,
        /// their implementations of getVariables aren't as fancy.
        /// </summary>
        internal class EnumerateDGrid : IEnumerator
        {
            private void InitBlock(DGrid penclosingInstance)
            {
                this.enclosingInstance = penclosingInstance;
            }

            private Object tempAuxObj;

            public virtual bool MoveNext()
            {
                bool result = hasMoreElements();
                if (result)
                {
                    tempAuxObj = nextElement();
                }
                return result;
            }

            public virtual void Reset()
            {
                tempAuxObj = null;
            }

            public virtual Object Current
            {
                get { return tempAuxObj; }
            }

            private DGrid enclosingInstance;

            public DGrid Enclosing_Instance
            {
                get { return enclosingInstance; }
            }

            internal bool array;
            internal IEnumerator e;

            internal EnumerateDGrid(DGrid enclosingInstance)
            {
                InitBlock(enclosingInstance);
                array = false; // true when the array is/has being/been
                // visited
                e = Enclosing_Instance.mapVars.GetEnumerator();
            }

            //UPGRADE_NOTE: The equivalent of method 'java.util.Enumeration.hasMoreElements' is not an override method. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1143'"
            public virtual bool hasMoreElements()
            {
                //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                return (array == false) || e.MoveNext();
            }

            //UPGRADE_NOTE: The equivalent of method 'java.util.Enumeration.nextElement' is not an override method. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1143'"
            public virtual Object nextElement()
            {
                if (!array)
                {
                    array = true;
                    return Enclosing_Instance.arrayVar;
                }
                else
                {
                    //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                    return e.Current;
                }
            }
        }

        /// <summary> Checks for internal consistency.  For <code>DGrid</code>, verify that
        /// the map variables have unique names and match the number of dimensions
        /// of the array variable.
        /// 
        /// </summary>
        /// <param name="all">for complex constructor types, this flag indicates whether to
        /// check the semantics of the member variables, too.
        /// </param>
        /// <throws>  BadSemanticsException if semantics are bad, explains why. </throws>
        /// <seealso cref="BaseType.CheckSemantics(bool)">
        /// </seealso>
        public override void CheckSemantics(bool all)
        {
            base.CheckSemantics(all);

            Utilities.UniqueNames(mapVars, Name, TypeName);

            if (arrayVar == null)
                throw new BadSemanticsException("DGrid.CheckSemantics(): Null grid base array in `" + Name + "'");

            // check semantics of array variable
            arrayVar.CheckSemantics(all);

            // enough maps?
            if (mapVars.Count != arrayVar.numDimensions())
                throw new BadSemanticsException("DGrid.CheckSemantics(): The number of map variables for grid `" + Name +
                                                "' does not match the number of dimensions of `" + arrayVar.Name + "'");

            //----- I added this next test 12/3/99. As soon as I did I questioned whether or not
            //----- it adds any value. ie: Can it ever happen that this test fails? I don't think
            //----- so now that I have written it...  ndp 12/3/99

            // Is the size of the maps equal to the size of the cooresponding dimensions?
            IEnumerator emap = mapVars.GetEnumerator();

            IEnumerator edims = arrayVar.Dimensions;
            int dim = 0;
            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            while (emap.MoveNext() && edims.MoveNext())
            {
                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                DArray thisMapArray = (DArray) emap.Current;
                IEnumerator ema = thisMapArray.Dimensions;
                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                ema.MoveNext();
                DArrayDimension thisMapDim = (DArrayDimension) ema.Current;

                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                DArrayDimension thisArrayDim = (DArrayDimension) edims.Current;

                if (thisMapDim.Size != thisArrayDim.Size)
                {
                    throw new BadSemanticsException("In grid '" + Name + " The size of dimension " + dim +
                                                    " in the array component '" + arrayVar.Name +
                                                    "is not equal to the size of the coresponding map vector '" +
                                                    thisMapArray.Name + ".");
                }
                dim++;
            }
            //----- end  ndp 12/3/99
        }


        /// <summary> Write the variable's declaration in a C-style syntax. This
        /// function is used to create textual representation of the Data
        /// Descriptor Structure (DDS).  See <em>The OPeNDAP User Manual</em> for
        /// information about this structure.
        /// 
        /// </summary>
        /// <param name="os">        The <code>StreamWriter</code> on which to Print the
        /// declaration.
        /// </param>
        /// <param name="space">     Each line of the declaration will begin with the
        /// characters in this string.  Usually used for leading spaces.
        /// </param>
        /// <param name="print_semi">a bool value indicating whether to Print a
        /// semicolon at the end of the declaration.
        /// </param>
        /// <param name="constrained"></param>
        /// <seealso cref="BaseType.PrintDeclaration(StreamWriter,string,bool)">
        /// </seealso>
        public override void PrintDeclaration(StreamWriter os, String space, bool print_semi, bool constrained)
        {
            //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
            os.WriteLine(space + TypeName + " {");
            //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
            os.WriteLine(space + " ARRAY:");
            arrayVar.PrintDeclaration(os, space + "    ", true);
            //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
            os.WriteLine(space + " MAPS:");
            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            for (IEnumerator e = mapVars.GetEnumerator(); e.MoveNext();)
            {
                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                BaseType bt = (BaseType) e.Current;
                bt.PrintDeclaration(os, space + "    ", true);
            }
            os.Write(space + "} " + Name);
            if (print_semi)
            {
                //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
                os.WriteLine(";");
            }
        }

        /// <summary> Prints the value of the variable, with its declaration.  This
        /// function is primarily intended for debugging OPeNDAP applications and
        /// text-based clients such as geturl.
        /// 
        /// </summary>
        /// <param name="os">          the <code>StreamWriter</code> on which to Print the value.
        /// </param>
        /// <param name="space">       this value is passed to the <code>PrintDeclaration</code> method,
        /// and controls the leading spaces of the output.
        /// </param>
        /// <param name="print_decl_p">a bool value controlling whether the
        /// variable declaration is printed as well as the value.
        /// </param>
        /// <seealso cref="BaseType.PrintValue(StreamWriter,string,bool)">
        /// </seealso>
        public override void PrintValue(StreamWriter os, String space, bool print_decl_p)
        {
            if (print_decl_p)
            {
                PrintDeclaration(os, space, false);
                os.Write(" = ");
            }

            os.Write("{ ARRAY: ");
            arrayVar.PrintValue(os, "", false);

            os.Write(" MAPS: ");
            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            for (IEnumerator e = mapVars.GetEnumerator(); e.MoveNext();)
            {
                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                BaseType bt = (BaseType) e.Current;
                bt.PrintValue(os, "", false);
                //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                if (e.MoveNext())
                    os.Write(", ");
            }
            os.Write(" }");

            if (print_decl_p)
            {
                //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
                os.WriteLine(";");
            }
        }

        /// <summary> Reads data from a <code>DataInputStream</code>. This method is only used
        /// on the client side of the OPeNDAP client/server connection.
        /// 
        /// </summary>
        /// <param name="source">  a <code>DataInputStream</code> to Read from.
        /// </param>
        /// <param name="sv">      the <code>ServerVersion</code> returned by the server.
        /// </param>
        /// <param name="statusUI">the <code>StatusUI</code> object to use for GUI updates
        /// and user cancellation notification (may be null).
        /// </param>
        /// <throws>  EOFException      if EOF is found before the variable is completely </throws>
        /// <summary>                           deserialized.
        /// </summary>
        /// <throws>  IOException       thrown on any other InputStream exception. </throws>
        /// <throws>  DataReadException if an unexpected value was Read. </throws>
        /// <seealso cref="IClientIO.Deserialize(BinaryReader, ServerVersion, IStatusUI)">
        /// </seealso>
        //UPGRADE_TODO: Class 'java.io.DataInputStream' was converted to 'System.IO.BinaryReader' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataInputStream'"
        //UPGRADE_NOTE: Synchronized keyword was removed from method 'Deserialize'. Lock expression was added. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1027'"
        public virtual void Deserialize(BinaryReader source, ServerVersion sv, IStatusUI statusUI)
        {
            lock (this)
            {
                arrayVar.Deserialize(source, sv, statusUI);
                //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                for (IEnumerator e = mapVars.GetEnumerator(); e.MoveNext();)
                {
                    if (statusUI != null && statusUI.UserCancelled())
                        throw new DataReadException("DGrid.Deserialize(): User cancelled");
                    //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                    IClientIO bt = (IClientIO) e.Current;
                    bt.Deserialize(source, sv, statusUI);
                }
            }
        }

        /// <summary> Writes data to a <code>DataOutputStream</code>. This method is used
        /// primarily by GUI clients which need to download OPeNDAP data, manipulate
        /// it, and then re-save it as a binary file.
        /// 
        /// </summary>
        /// <param name="sink">a <code>DataOutputStream</code> to write to.
        /// </param>
        /// <throws>  IOException thrown on any <code>OutputStream</code> </throws>
        /// <summary>                     exception.
        /// </summary>
        //UPGRADE_TODO: Class 'java.io.DataOutputStream' was converted to 'System.IO.BinaryWriter' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataOutputStream'"
        public virtual void Externalize(BinaryWriter sink)
        {
            arrayVar.Externalize(sink);
            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            for (IEnumerator e = mapVars.GetEnumerator(); e.MoveNext();)
            {
                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                IClientIO bt = (IClientIO) e.Current;
                bt.Externalize(sink);
            }
        }


        /// <summary> </summary>
        /// <param name="pw">
        /// </param>
        /// <param name="pad">
        /// </param>
        /// <param name="constrained">
        /// </param>
        /// <opendap.ddx.experimental>  </opendap.ddx.experimental>
        public override void PrintXML(StreamWriter pw, String pad, bool constrained)
        {
            pw.Write(pad + "<Grid");
            if (Name != null)
            {
                pw.Write(" name=\"" + DDSXMLParser.normalizeToXML(ClearName) + "\"");
            }
            //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
            pw.WriteLine(">");

            IEnumerator e = AttributeNames.GetEnumerator();

            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            while (e.MoveNext())
            {
                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                String aName = (String) e.Current;


                try
                {
                    Attribute a = GetAttribute(aName);
                    a.printXML(pw, pad + "\t", constrained);
                }
                catch (NoSuchAttributeException )
                {
                }
            }

            arrayVar.PrintXML(pw, pad + "\t", constrained);


            e = mapVars.GetEnumerator();
            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            while (e.MoveNext())
            {
                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                DArray map = (DArray) e.Current;

                map.printAsMapXML(pw, pad + "\t", constrained);
            }


            //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
            pw.WriteLine(pad + "</Grid>");
        }
    }
}